#ifndef GAMESERVER_H
#define GAMESERVER_H

// Libraries
#include <SFML/System.hpp>
//#include <SFML/Network.hpp>

// C++
//#define _USE_MATH_DEFINES
//#include <math.h>
//#include <iostream>
//#include <sstream>
//#include <map>
#include <list>
//#include <vector>

// Local
#include "gameobject.h"
#include "gameworld.h"
#include "player.h"
#include "network.h"
#include "sbconstants.h"
#include "packetparser.h"
#include "change.h"

class GameServer : private sf::Thread, public PacketParser, private GameworldEventListener
{
	public:
		GameServer();
		virtual ~GameServer();
		bool Start(unsigned short port);
		void Stop();
		bool IsRunning();

		// TODO: Some kind of interface the console can use to pass commands
		int GetNumClients();
		int GetGlobalChangeQueueLength();
		int GetNextChangeNumber();
		int GetWorldTime();

		void PopulateWorld();

	private:
		virtual void Run();
		void UpdateClient(Player& client);
		void ProcessPacketQueue();

		void HandleAdminPacket(
				sf::IPAddress sender,
				unsigned short port,
				sf::Uint32 clientID,
				sf::Packet& packet);

		void HandleConnectionPacket(
				sf::IPAddress sender,
				unsigned short port,
				sf::Uint32 clientID,
				sf::Packet& packet);

		void HandleWorldUpdatePacket(
				sf::IPAddress sender,
				unsigned short port,
				sf::Uint32 clientID,
				sf::Packet& packet);



		bool isRunning;
		sf::Clock timer;
		sf::Mutex gameserverMutex;
		Network network;

		// List of changes in the game. Changes are deleted from the front of the queue as all
		// clients get up to date.
		std::list<Change*> changes;

		sf::Uint32 nextClientID;
		sf::Uint32 nextChangeNumber;
		std::map<sf::Uint32, Player*> clients;
		sf::Uint32 numClients;

		GameWorld gameworld;

		void ObjectCreated(const GameObject& object);
		void ObjectDeleted(const GameObject& object);
		void ShipKilled(const GameObject& object);
		void ShipControlChanged(const GameObject& object);
};
#endif // GAMESERVER_H
